<?php

namespace App\Models\Customer;

use App\Models\Concerns\ScopeFilterable;
use App\Models\Store\Store;
use App\Observers\BosCleanObserver;
use App\Services\Utils\Bosable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * @property int id
 * @property int banner_type_id
 *
 * @property-read array|null data
 *
 * @mixin Builder
 * @method static self filterDeviceAccountId(int $device_account_id)
 * @method static self filterStoreId(int $store_id)
 * @method static self filterAppBannerTypeId(int $banner_type_id)
 * @method static self filterName(string $name)
 */
class Banner extends Model
{
    use Bosable,
        ScopeFilterable;

    const CUSTOMER_ID_PANX = 0; // panx 推广时用

    protected $table = 'banners';

    protected $guarded = [];

    protected $casts = [
        'banner_type_id' => 'int'

        /**
         * @see getDataAttribute
         */
//        'data' => 'array',
    ];

    public $key_bos_key_prefix = 'app_banner/';

    public $bos_columns = ['image'];

    protected $dates = [
        'started_at',
        'ended_at'
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function stores()
    {
        return $this->morphedByMany(Store::class, 'bannerable');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function getStores()
    {
        return $this->stores()->select(['stores.id', 'stores.name']);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function deviceAccounts()
    {
        return $this->morphedByMany(DeviceAccount::class, 'bannerable');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function getDeviceAccounts()
    {
        return $this->deviceAccounts()->select(['device_accounts.id', 'device_accounts.account', 'device_accounts.device_name']);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function bannerType()
    {
        return $this->belongsTo(BannerType::class, 'banner_type_id', 'id');
    }

    /**
     * @return null|string
     */
    public function getImageAttribute()
    {
        if (!$this->attributes['image']) return null;

        return $this->getStaticUrl($this->attributes['image']);
    }

    /**
     * @param $image
     * @throws \Exception
     */
    public function setImageAttribute($image)
    {
        if (is_file($image)) {
            $this->attributes['image'] = $this->uploadPostFile($image, $this->key_bos_key_prefix);
        }
    }

    /**
     * @used-by data
     *
     * @return array|string|null
     */
    public function getDataAttribute()
    {
        $data_json = $this->attributes['data'];

        $data = json_decode($data_json, true);

        // 兼容之前 App 跳转商品保存的是 spu_code 字符串的情况
        if ($this->banner_type_id === BannerType::ID_TO_PRODUCT) {
            return $data['spu_code'] ?? $data_json;
        }

        return $data;
    }

    /**
     * @used-by filterStoreId
     *
     * @param Builder $query
     * @param $store_id
     * @return Builder
     */
    public function scopeFilterStoreId(Builder $query, $store_id)
    {
        if (!$store_id) return $query;

        return $query->whereHas('stores', function (Builder $query) use ($store_id) {
            return $query->where('stores.id', $store_id);
        });
    }

    /**
     * @used-by filterDeviceAccountId
     *
     * @param Builder $query
     * @param $device_account_id
     * @return Builder
     */
    public function scopeFilterDeviceAccountId(Builder $query, $device_account_id)
    {
        if (!$device_account_id) return $query;

        return $query->whereHas('deviceAccounts', function (Builder $query) use ($device_account_id) {
            return $query->where('device_accounts.id', $device_account_id);
        });
    }

    /**
     * @used-by filterAppBannerTypeId
     *
     * @param Builder $query
     * @param $app_banner_type_id
     * @return Builder
     */
    public function scopeFilterAppBannerTypeId(Builder $query, $app_banner_type_id)
    {
        if (!$app_banner_type_id) return $query;

        return $query->whereHas('bannerType', function (Builder $query) use ($app_banner_type_id) {
            return $query->where('banner_types.id', $app_banner_type_id);
        });
    }

    /**
     * @used-by filterName
     *
     * @param Builder $query
     * @param $name
     * @return Builder
     */
    public function scopeFilterName(Builder $query, $name)
    {
        if (!$name) return $query;

        return $query->where('name', 'like', '%' . $name . '%');
    }

    /**
     * 注册删除 bosKey 事件绑定
     */
    protected static function boot()
    {
        parent::boot();

        /*
         * 监听bos清理事件
         */
        self::observe(BosCleanObserver::class);
    }

}
